﻿Imports System.Reflection

''' <summary>
''' Represents the learned schema of a database, which includes references to all tables that make up the database.
''' This class provides an interface that allows a complete schema to be generated based on attributes applied to
''' parts of code in an assembly. The resulting schema can then be used to get information about the database
''' at run-time.
''' </summary>
Public Class DatabaseSchema

    Private _tables As New List(Of TableSchema)

    ''' <summary>
    ''' Gets all of the tables that make up the database.
    ''' </summary>
    ''' <value>The list of all available tables.</value>
    Default Public ReadOnly Property Tables(ByVal tableName As String) As TableSchema
        Get
            For Each Table As TableSchema In _tables
                If Table.Name = tableName Then Return Table
            Next
            Throw New Exception("Table '" + tableName + "' does not exist in the schema.")
        End Get
    End Property

    ''' <summary>
    ''' Gets all of the tables in the schema.
    ''' </summary>
    ''' <value>All of the available tables.</value>
    Public ReadOnly Property AllTables As TableSchema()
        Get
            Return _tables.ToArray
        End Get
    End Property

    Private Sub New()

    End Sub

    ''' <summary>
    ''' Compiles a complete schema based on the code that makes up the specified assembly.
    ''' </summary>
    ''' <param name="assembly">The assembly containing the schema of the database.</param>
    ''' <returns>The schema of the database.</returns>
    Public Shared Function Compile(ByVal assembly As Assembly) As DatabaseSchema

        ' Find tables in the given assembly
        Dim Result As New DatabaseSchema()
        For Each Type As Type In assembly.GetTypes
            Dim TableLabel As TableAttribute = GetAttribute(Of TableAttribute)(Type)
            If TableLabel IsNot Nothing Then

                ' Get the schema of this table
                Dim Table As TableSchema = TableSchema.Create(Result, Type)
                Result._tables.Add(Table)

            End If
        Next

        ' Return the schema
        Return Result

    End Function

    ''' <summary>
    ''' Compiles a complete schema based on code that makes up the calling assembly.
    ''' </summary>
    ''' <returns>The schema of the database.</returns>
    Public Shared Function Compile() As DatabaseSchema
        Return Compile(Assembly.GetCallingAssembly)
    End Function

End Class
